import './ChessBoard.css'
import React from 'react';

enum QiziColor {
    WHITE,
    BLACK
}

class Qizi {
    public x: number;
    public y: number;
    public color: QiziColor;

    constructor(x: number, y: number, color: QiziColor) {
        this.x = x;
        this.y = y;
        this.color = color;
    }

    public toJson() {
        return {
            x: this.x,
            y: this.y,
            c: this.color === QiziColor.WHITE
        }
    }
}

class ChessBoard extends React.Component {
    private canvas: HTMLCanvasElement | null;
    private ctx: CanvasRenderingContext2D | null;

    /**
     * 棋盘的最大大小
     * @private
     */
    private size: number;

    /**
     * 格子的大小
     * @private
     */
    private gzSize: number;


    /**
     * 棋子的大小
     * @private
     */
    private qzSize: number;

    private turn: QiziColor;

    private t: any


    private stack: Array<Qizi>;

    constructor(props: any) {
        super(props);
        this.canvas = null;
        this.ctx = null;
        this.state = {}
        this.stack = [];
        this.turn = QiziColor.BLACK;

        this.size = 800;
        this.gzSize = this.size / 16;
        this.qzSize = this.gzSize / 3;
    }

    componentDidMount() {
        this.reloadQijuFromLocalStorage();

        if (this.canvas?.getContext('2d')) {
            this.ctx = this.canvas?.getContext('2d');
            this.size = Math.min(this.canvas?.clientWidth, this.canvas?.clientHeight);
            this.canvas.width = this.size;
            this.canvas.height = this.size;
            this.gzSize = this.size / 16;
            this.qzSize = this.gzSize / 3;

            if (this.ctx != null) {
                this.reDraw();
            }
        }
    }

    reloadQijuFromLocalStorage() {
        let ju = localStorage.getItem('ju');
        if (ju) {
            this.stack = JSON.parse(ju)
        }
    }

    render() {
        return <canvas ref={ref => this.canvas = ref}
            className={'qipan'}
            onMouseOver={(e) => this.onmouseover(e)}
            onMouseMove={(e) => this.onmousemove(e)}
            onClick={(e) => this.onclick(e)} />;
    }

    onmouseover(event: React.MouseEvent<HTMLCanvasElement>) {

    }

    onmousemove(event: React.MouseEvent<HTMLCanvasElement>) {
        let target: any = event.target;
        if (this.canvas != null) {
            let x = event.clientX - target.getBoundingClientRect().left;
            let y = event.clientY - target.getBoundingClientRect().top;

            let hint = this.calcHint(x, y);
            if (hint != null) {
                this.drawHint(hint[0], hint[1]);
            }
        }
    }

    private calcHint(x: number, y: number) {
        let posX = Math.round(x / this.gzSize);
        let posY = Math.round(y / this.gzSize);
        if (posX > 0 && posX < 16 && posY > 0 && posY < 16) {  //合理范围内
            return [posX, posY]
        }
        return null;
    }

    /**
     * 根据鼠标的位置画出暗示的点位
     * @param posX
     * @param posY
     * @private
     */
    private drawHint(posX: number, posY: number) {
        clearTimeout(this.t);
        const callback = () => this.drawQiziHint(this.getPositionByXY(posX, posY));
        this.t = setTimeout(callback, 10);
    }

    onclick(event: React.MouseEvent<HTMLCanvasElement>) {
        let target: any = event.target;
        if (this.canvas != null) {
            let x = event.clientX - target.getBoundingClientRect().left;
            let y = event.clientY - target.getBoundingClientRect().top;

            let hint = this.calcHint(x, y);
            if (hint != null) {
                this.luozi(hint[0], hint[1]);
            }
        }
    }

    luozi(posX: number, posY: number) {
        for (let i = 0; i < this.stack.length; i++) {
            if (this.stack[i].x === posX && this.stack[i].y === posY) {
                console.log("exist qizi now!!!");
                return;
            }
        }

        this.stack.push(new Qizi(posX, posY, this.turn))

        this.turn = this.turn === QiziColor.WHITE ? QiziColor.BLACK : QiziColor.WHITE;

        localStorage.setItem('ju', JSON.stringify(this.stack));
    }

    /**
     * 根据棋盘的点获取坐标
     * @param x x方位的坐标
     * @param y y方位的坐标
     * @private
     */
    private getPositionByXY(x: number, y: number): number[] {
        return [x * this.gzSize, y * this.gzSize]
    }

    private paintGeZi() {
        if (this.ctx == null) return;
        this.ctx.clearRect(0, 0, this.size, this.size);

        this.ctx.strokeStyle = '#474545';
        this.ctx.fillStyle = '#474545';
        this.ctx.lineWidth = 2;

        //画横排
        for (let i = 1; i < 16; i++) {
            let start = this.getPositionByXY(1, i);
            this.ctx.moveTo(start[0], start[1]);

            let end = this.getPositionByXY(15, i);
            this.ctx.lineTo(end[0], end[1])
        }

        //画纵排
        for (let i = 1; i < 16; i++) {
            let start = this.getPositionByXY(i, 1);
            this.ctx.moveTo(start[0], start[1]);

            let end = this.getPositionByXY(i, 15);
            this.ctx.lineTo(end[0], end[1])
        }

        this.ctx.stroke();

        //画定位点
        this.drawAnchorPoint(this.getPositionByXY(4, 4));
        this.drawAnchorPoint(this.getPositionByXY(12, 4));
        this.drawAnchorPoint(this.getPositionByXY(4, 12));
        this.drawAnchorPoint(this.getPositionByXY(12, 12));

        this.ctx.lineWidth = 0;
    }

    private drawAnchorPoint(pos: number[]) {
        if (this.ctx == null) return;

        this.ctx.beginPath();
        this.ctx.arc(pos[0], pos[1], this.gzSize / 10, 0, 2 * Math.PI);
        this.ctx.fill()
    }

    /**
     * 恢复棋局
     * @private
     */
    private restoreJu() {
        for (let i = 0; i < this.stack.length; i++) {
            this.drawQizi(this.stack[i].x, this.stack[i].y, this.stack[i].color);
        }
    }

    private drawQizi(posX: number, posY: number, color: QiziColor) {
        if (this.ctx == null) return;
        let pos = this.getPositionByXY(posX, posY);
        let grad = this.ctx.createRadialGradient(pos[0], pos[1], this.qzSize / 3, pos[0], pos[1], this.qzSize);
        grad.addColorStop(0, color === QiziColor.WHITE ? 'Azure' : 'Black')
        grad.addColorStop(1, 'gray')
        this.ctx.fillStyle = grad;

        this.ctx.beginPath();
        this.ctx.arc(pos[0], pos[1], this.qzSize, 0, 2 * Math.PI);
        this.ctx.fill()
    }

    private reDraw() {
        this.paintGeZi();
        this.restoreJu();
    }

    private drawQiziHint(pos: number[]) {
        if (this.ctx == null) return;
        this.reDraw();

        let grad = this.ctx.createRadialGradient(pos[0], pos[1], this.qzSize / 3, pos[0], pos[1], this.qzSize);
        grad.addColorStop(0, this.turn === QiziColor.WHITE ? 'Azure' : 'Black')
        grad.addColorStop(1, 'gray')
        this.ctx.fillStyle = grad;

        this.ctx.beginPath();
        this.ctx.arc(pos[0], pos[1], this.qzSize, 0, 2 * Math.PI);
        this.ctx.fill()
    }
}

export default ChessBoard